using System;
using CKY.AgentPlatform.Security;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Security.Encryption;
using CKY.AgentPlatform.Users;
using CKY.AgentPlatform.Users.Dtos;
using CKY.AgentPlatform.Security;
using CKY.AgentPlatform.Authorization;

namespace CKY.AgentPlatform.Users
{
    /// <summary>
    /// 用户认证应用服务
    /// </summary>
    public class UserAuthAppService : ApplicationService, IUserAuthAppService
    {
        private readonly IRepository<PlatformUser, Guid> _userRepository;
        private readonly IRepository<Role, Guid> _roleRepository;
        private readonly IRepository<UserRole, Guid> _userRoleRepository;
        private readonly SimpleJwtTokenService _jwtTokenService;
        private readonly IStringEncryptionService _stringEncryptionService;
        private readonly ILogger<UserAuthAppService> _logger;
        private readonly IConfiguration _configuration;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public UserAuthAppService(
            IRepository<PlatformUser, Guid> userRepository,
            IRepository<Role, Guid> roleRepository,
            IRepository<UserRole, Guid> userRoleRepository,
            SimpleJwtTokenService jwtTokenService,
            IStringEncryptionService stringEncryptionService,
            ILogger<UserAuthAppService> logger,
            IConfiguration configuration,
            IHttpContextAccessor httpContextAccessor)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _userRoleRepository = userRoleRepository;
            _jwtTokenService = jwtTokenService;
            _stringEncryptionService = stringEncryptionService;
            _logger = logger;
            _configuration = configuration;
            _httpContextAccessor = httpContextAccessor;
        }

        private string GetCurrentIpAddress()
        {
            var httpContext = _httpContextAccessor?.HttpContext;
            if (httpContext != null)
            {
                var remoteIpAddress = httpContext.Connection.RemoteIpAddress;
                if (remoteIpAddress != null)
                {
                    return remoteIpAddress.ToString();
                }
            }
            return "127.0.0.1";
        }
        /// <summary>
        /// 用户登录
        /// </summary>
        public async Task<UserAuthResultDto> LoginAsync(UserLoginDto input)
        {
            try
            {
                // 查找用户
                var user = await FindUserByUsernameOrEmailAsync(input.UsernameOrEmail);
                if (user == null)
                {
                    _logger.LogWarning("登录失败：用户不存在 - {UsernameOrEmail}", input.UsernameOrEmail);
                    return CreateFailedResult("用户名或密码错误", "USER_NOT_FOUND");
                }

                // 检查用户状态
                if (!user.IsActive)
                {
                    _logger.LogWarning("登录失败：用户已停用 - {Username}", user.UserName);
                    return CreateFailedResult("用户账户已停用", "USER_INACTIVE");
                }

                if (user.IsLockedOut)
                {
                    _logger.LogWarning("登录失败：用户已锁定 - {Username}", user.UserName);
                    return CreateFailedResult("用户账户已锁定，请稍后再试", "USER_LOCKED_OUT");
                }

                // 验证密码
                if (!await VerifyPasswordAsync(user, input.Password))
                {
                    user.IncrementAccessFailedCount();
                    await _userRepository.UpdateAsync(user);

                    _logger.LogWarning("登录失败：密码错误 - {Username}, 失败次数：{Count}", 
                        user.UserName, user.AccessFailedCount);
                    return CreateFailedResult("用户名或密码错误", "INVALID_PASSWORD");
                }

                // 获取用户角色和权限
                var roles = await GetUserRolesAsync(user.Id);
                var permissions = await GetUserPermissionsAsync(user.Id, roles);

                // 生成令牌
                var accessToken = _jwtTokenService.GenerateAccessToken(user.Id, string.Join(",", roles), permissions.ToList());
                var refreshToken = _jwtTokenService.GenerateRefreshToken();

                // 更新登录信息
                user.RecordLogin(GetCurrentIpAddress());
                user.ResetAccessFailedCount();
                await _userRepository.UpdateAsync(user);

                _logger.LogInformation("用户登录成功 - {Username}", user.UserName);

                return new UserAuthResultDto
                {
                    Success = true,
                    AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    TokenType = "Bearer",
                    ExpiresIn = int.Parse(_configuration["Jwt:ExpirationInMinutes"] ?? "30") * 60,
                    User = await MapToUserInfoDtoAsync(user, roles, permissions)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户登录异常 - {UsernameOrEmail}", input.UsernameOrEmail);
                return CreateFailedResult("登录过程中发生错误", "LOGIN_ERROR");
            }
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        public async Task<UserAuthResultDto> RegisterAsync(UserRegisterDto input)
        {
            try
            {
                // 检查用户名是否已存在
                if (await _userRepository.AnyAsync(x => x.UserName == input.UserName))
                {
                    return CreateFailedResult("用户名已存在", "USERNAME_EXISTS");
                }

                // 检查邮箱是否已存在
                if (await _userRepository.AnyAsync(x => x.Email == input.Email))
                {
                    return CreateFailedResult("邮箱已被注册", "EMAIL_EXISTS");
                }

                // 创建用户
                var user = new PlatformUser(
                    GuidGenerator.Create(),
                    input.UserName,
                    input.Email,
                    input.Name,
                    input.Surname)
                {
                    PhoneNumber = input.PhoneNumber,
                    Department = input.Department,
                    Position = input.Position
                };

                // 设置密码
                user.PasswordHash = await HashPasswordAsync(input.Password);

                // 保存用户
                await _userRepository.InsertAsync(user);

                // 分配默认角色
                await AssignDefaultRolesAsync(user.Id);

                // 获取用户角色和权限
                var roles = await GetUserRolesAsync(user.Id);
                var permissions = await GetUserPermissionsAsync(user.Id, roles);

                // 生成令牌
                var accessToken = _jwtTokenService.GenerateAccessToken(user.Id, string.Join(",", roles), permissions.ToList());
                var refreshToken = _jwtTokenService.GenerateRefreshToken();

                _logger.LogInformation("用户注册成功 - {Username}", user.UserName);

                return new UserAuthResultDto
                {
                    Success = true,
                    AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    TokenType = "Bearer",
                    ExpiresIn = int.Parse(_configuration["Jwt:ExpirationInMinutes"] ?? "30") * 60,
                    User = await MapToUserInfoDtoAsync(user, roles, permissions)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户注册异常 - {Username}", input.UserName);
                return CreateFailedResult("注册过程中发生错误", "REGISTER_ERROR");
            }
        }

        /// <summary>
        /// 用户登出
        /// </summary>
        public async Task<bool> LogoutAsync(Guid userId)
        {
            try
            {
                // 在实际应用中，可以将刷新令牌加入黑名单
                _logger.LogInformation("用户登出 - {UserId}", userId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户登出异常 - {UserId}", userId);
                return false;
            }
        }

        /// <summary>
        /// 刷新访问令牌
        /// </summary>
        public async Task<UserAuthResultDto> RefreshTokenAsync(RefreshTokenDto input)
        {
            try
            {
                // 验证刷新令牌
                var isValid = _jwtTokenService.ValidateRefreshToken(input.RefreshToken);
                if (!isValid)
                {
                    return CreateFailedResult("无效的刷新令牌", "INVALID_REFRESH_TOKEN");
                }

                // 获取用户信息
                var user = await _userRepository.GetAsync(input.UserId);
                if (!user.IsActive)
                {
                    return CreateFailedResult("用户账户已停用", "USER_INACTIVE");
                }

                // 获取用户角色和权限
                var roles = await GetUserRolesAsync(user.Id);
                var permissions = await GetUserPermissionsAsync(user.Id, roles);

                // 生成新的令牌
                var accessToken = _jwtTokenService.GenerateAccessToken(user.Id, string.Join(",", roles), permissions.ToList());
                var refreshToken = _jwtTokenService.GenerateRefreshToken();

                return new UserAuthResultDto
                {
                    Success = true,
                    AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    TokenType = "Bearer",
                    ExpiresIn = int.Parse(_configuration["Jwt:ExpirationInMinutes"] ?? "30") * 60,
                    User = await MapToUserInfoDtoAsync(user, roles, permissions)
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "刷新令牌异常 - {UserId}", input.UserId);
                return CreateFailedResult("刷新令牌过程中发生错误", "REFRESH_TOKEN_ERROR");
            }
        }

        /// <summary>
        /// 获取当前用户信息
        /// </summary>
        public async Task<UserInfoDto> GetCurrentUserAsync()
        {
            var userId = CurrentUser.Id ?? Guid.Empty;
            var user = await _userRepository.FirstOrDefaultAsync(u => u.Id == userId);
            
            var roles = await GetUserRolesAsync(user.Id);
            var permissions = await GetUserPermissionsAsync(user.Id, roles);

            return await MapToUserInfoDtoAsync(user, roles, permissions);
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        public async Task<bool> ChangePasswordAsync(ChangePasswordDto input)
        {
            try
            {
                var userId = CurrentUser.Id ?? Guid.Empty;
                var user = await _userRepository.FirstOrDefaultAsync(u => u.Id == userId);

                // 验证当前密码
                if (!await VerifyPasswordAsync(user, input.CurrentPassword))
                {
                    _logger.LogWarning("修改密码失败：当前密码错误 - {Username}", user.UserName);
                    return false;
                }

                // 设置新密码
                user.PasswordHash = await HashPasswordAsync(input.NewPassword);
                await _userRepository.UpdateAsync(user);

                _logger.LogInformation("用户修改密码成功 - {Username}", user.UserName);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "修改密码异常 - {UserId}", CurrentUser.Id);
                return false;
            }
        }

        /// <summary>
        /// 忘记密码
        /// </summary>
        public async Task<bool> ForgotPasswordAsync(ForgotPasswordDto input)
        {
            try
            {
                var user = await _userRepository.FirstOrDefaultAsync(x => x.Email == input.Email);
                if (user == null)
                {
                    _logger.LogWarning("忘记密码失败：邮箱不存在 - {Email}", input.Email);
                    return false;
                }

                // 生成重置令牌
                var resetToken = GenerateResetToken();
                
                // 在实际应用中，这里应该发送重置邮件
                // 这里简化处理，直接记录日志
                _logger.LogInformation("生成密码重置令牌 - {Username}, Token: {Token}", 
                    user.UserName, resetToken);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "忘记密码异常 - {Email}", input.Email);
                return false;
            }
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        public async Task<bool> ResetPasswordAsync(ResetPasswordDto input)
        {
            try
            {
                var user = await FindUserByUsernameOrEmailAsync(input.UsernameOrEmail);
                if (user == null)
                {
                    return false;
                }

                // 验证重置令牌（简化版本）
                if (!ValidateResetToken(input.ResetToken))
                {
                    return false;
                }

                // 设置新密码
                user.PasswordHash = await HashPasswordAsync(input.NewPassword);
                user.ResetAccessFailedCount();
                await _userRepository.UpdateAsync(user);

                _logger.LogInformation("用户重置密码成功 - {Username}", user.UserName);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "重置密码异常 - {UsernameOrEmail}", input.UsernameOrEmail);
                return false;
            }
        }

        /// <summary>
        /// 验证用户权限
        /// </summary>
        public async Task<bool> HasPermissionAsync(string permission)
        {
            var userId = CurrentUser.Id ?? Guid.Empty;
            var user = await _userRepository.FirstOrDefaultAsync(u => u.Id == userId);
            
            var roles = await GetUserRolesAsync(user.Id);
            var permissions = await GetUserPermissionsAsync(user.Id, roles);

            return permissions.Contains(permission);
        }

        /// <summary>
        /// 验证用户角色
        /// </summary>
        public async Task<bool> IsInRoleAsync(string role)
        {
            var userId = CurrentUser.Id ?? Guid.Empty;
            var roles = await GetUserRolesAsync(userId);
            return roles.Contains(role);
        }

        // 其他方法实现（简化版本）
        public Task<bool> EnableTwoFactorAuthAsync() => Task.FromResult(true);
        public Task<bool> DisableTwoFactorAuthAsync() => Task.FromResult(true);
        public Task<bool> VerifyTwoFactorCodeAsync(string code) => Task.FromResult(true);
        public Task<bool> ConfirmEmailAsync(string token) => Task.FromResult(true);
        public Task<bool> ResendEmailConfirmationAsync() => Task.FromResult(true);
        public Task<bool> ConfirmPhoneNumberAsync(string code) => Task.FromResult(true);
        public Task<bool> SendPhoneNumberVerificationAsync() => Task.FromResult(true);

        #region 私有方法

        private async Task<PlatformUser> FindUserByUsernameOrEmailAsync(string usernameOrEmail)
        {
            return await _userRepository.FirstOrDefaultAsync(x => 
                x.UserName == usernameOrEmail || x.Email == usernameOrEmail);
        }

        private async Task<List<string>> GetUserRolesAsync(Guid userId)
        {
            var userRoles = await _userRoleRepository.GetListAsync(x => x.UserId == userId && x.IsValid());
            var roleIds = userRoles.Select(x => x.RoleId).ToList();
            
            if (!roleIds.Any())
            {
                return new List<string>();
            }

            var roles = await _roleRepository.GetListAsync(x => roleIds.Contains(x.Id));
            return roles.Select(x => x.Name).ToList();
        }

        private async Task<List<string>> GetUserPermissionsAsync(Guid userId, List<string> roleNames)
        {
            var permissions = new HashSet<string>();

            // 获取角色的权限
            if (roleNames.Any())
            {
                var roles = await _roleRepository.GetListAsync(x => roleNames.Contains(x.Name));
                foreach (var role in roles)
                {
                    foreach (var permission in role.Permissions)
                    {
                        permissions.Add(permission);
                    }
                }
            }

            // 管理员拥有所有权限
            var user = await _userRepository.FirstOrDefaultAsync(u => u.Id == userId);
            if (user.IsAdmin)
            {
                permissions.Add("AgentPlatform.Admin");
            }

            return permissions.ToList();
        }

        private async Task AssignDefaultRolesAsync(Guid userId)
        {
            // 分配默认用户角色
            var defaultRole = await _roleRepository.FirstOrDefaultAsync(x => x.IsDefault);
            if (defaultRole != null)
            {
                var userRole = new UserRole(
                    GuidGenerator.Create(),
                    userId,
                    defaultRole.Id,
                    CurrentUser.Id);
                
                await _userRoleRepository.InsertAsync(userRole);
            }
        }

        private async Task<UserInfoDto> MapToUserInfoDtoAsync(PlatformUser user, List<string> roles, List<string> permissions)
        {
            return new UserInfoDto
            {
                Id = user.Id,
                UserName = user.UserName,
                Email = user.Email,
                Name = user.Name,
                Surname = user.Surname,
                PhoneNumber = user.PhoneNumber,
                AvatarUrl = user.AvatarUrl,
                Department = user.Department,
                Position = user.Position,
                EmailConfirmed = user.EmailConfirmed,
                PhoneNumberConfirmed = user.PhoneNumberConfirmed,
                TwoFactorEnabled = user.TwoFactorEnabled,
                IsAdmin = user.IsAdmin,
                IsActive = user.IsActive,
                LastLoginTime = user.LastLoginTime,
                Roles = roles,
                Permissions = permissions
            };
        }

        private async Task<string> HashPasswordAsync(string password)
        {
            var hasher = new PasswordHasher<PlatformUser>();
            return hasher.HashPassword(null, password);
        }

        private async Task<bool> VerifyPasswordAsync(PlatformUser user, string password)
        {
            var hasher = new PasswordHasher<PlatformUser>();
            var result = hasher.VerifyHashedPassword(user, user.PasswordHash, password);
            return result == PasswordVerificationResult.Success;
        }

        private string GenerateResetToken()
        {
            var randomNumber = new byte[32];
            using var rng = RandomNumberGenerator.Create();
            rng.GetBytes(randomNumber);
            return Convert.ToBase64String(randomNumber);
        }

        private bool ValidateResetToken(string token)
        {
            // 简化的令牌验证，实际应用中应该检查令牌的有效性和过期时间
            return !string.IsNullOrEmpty(token) && token.Length > 32;
        }

        private UserAuthResultDto CreateFailedResult(string errorMessage, string errorCode)
        {
            return new UserAuthResultDto
            {
                Success = false,
                ErrorMessage = errorMessage,
                ErrorCode = errorCode
            };
        }

        #endregion
    }
}